/**
 * 
 */
package net.teamix;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletRequest;

import net.teamix.Utils.TranslationComparator;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/**
 * @author "Svetoslav Batchovski"
 * 
 */
public class XMLService {

	public XMLDoc xmlDoc;

	public String changed = "0";

	public List<TranslationElement> getTranslationElements() {

		List<TranslationElement> translationList = new ArrayList<TranslationElement>();
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");

		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			List langNdList = element.getChildren("msg");
			String[] sprachen = new String[langNdList.size()];
			for (int j = 0; j < langNdList.size(); j++) {
				Element language = (Element) langNdList.get(j);
				if (!language.getChildren().isEmpty()
						|| !language.getTextTrim().equalsIgnoreCase(""))
					sprachen[j] = language.getAttributeValue("lang");
			}
			translationList.add(new TranslationElement(element
					.getAttributeValue("msgid"), sprachen));
			Collections.sort(translationList, new TranslationComparator());
		}

		return translationList;
	}

	public List<LangElement> getLangElements() {

		List<LangElement> langList = new ArrayList<LangElement>();

		List langNdList = null;
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");

		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				langNdList = element.getChildren("msg");
				i = ndList.size();
			}
		}
		for (int j = 0; j < langNdList.size(); j++) {
			Element language = (Element) langNdList.get(j);
			langList.add(new LangElement(language.getAttributeValue("lang"),
					getParameters(language)));
		}
		return langList;
	}

	public List<ParameterElement> getParameters(Element language) {

		List<ParameterElement> parameterList = new ArrayList<ParameterElement>();

		List testList = language.getChildren();
		if (null == language.getChildren())
			return parameterList;
		else if (null != language.getChild("inc"))
			parameterList.add(new ParameterElement("Include", language
					.getChild("inc").getAttributeValue("msgid"), 0));
		else if (null != language.getChild("para")) {
			List parameterNdList = language.getChildren();
			for (int i = 0; i < parameterNdList.size(); i++) {
				Element parameter = (Element) parameterNdList.get(i);
				parameterList.add(new ParameterElement("Paragraph", parameter
						.getText(), i));
			}
		} else if (!language.getTextTrim().equalsIgnoreCase(""))
			parameterList.add(new ParameterElement("Paragraph", language
					.getText(), 0));

		return parameterList;

	}

	public void addNewMsgID(String newMsgId) {
		setChanged("1");
		List<TranslationElement> translationList = new ArrayList<TranslationElement>();
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		Element newMsgElement = new Element("translation");
		newMsgElement.setAttribute("msgid", newMsgId);
		ndList.add(newMsgElement);
	}

	public void delMsgId(String msgId) {
		setChanged("1");
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(msgId)) {
				ndList.remove(element);
				return;
			}
		}
	}

	public void addSprache(String lang) {
		if (lang.length() < 1)
			return;
		setChanged("1");
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");
		Element newLang = null;
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				List languages = element.getChildren("msg");
				newLang = new Element("msg");
				newLang.setAttribute("lang", lang);
				languages.add(newLang);
				return;
			}
		}
	}

	public void addPara(String lang, String paragraph) {
		setChanged("1");
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");
		Element newPara = null;
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				List languages = element.getChildren("msg");
				for (int j = 0; j < languages.size(); j++) {
					Element language = (Element) languages.get(j);
					if (language.getAttributeValue("lang").equals(lang)) {
						if (null != language.getChild("para")) {
							List paragraphs = language.getChildren("para");
							newPara = new Element("para");
							newPara.setText(paragraph);
							paragraphs.add(newPara);
							return;
						} else if (language.getTextTrim().equalsIgnoreCase("")) {
							language.setText(paragraph);
							return;
						} else {
							List paragraphs = language.getChildren("para");
							String oldTxt = language.getText();
							language.removeContent();
							Element oldPara = new Element("para");
							oldPara.setText(oldTxt);
							paragraphs.add(oldPara);
							newPara = new Element("para");
							newPara.setText(paragraph);
							paragraphs.add(newPara);
							return;
						}
					}
				}
			}
		}
	}

	public void addInc(String lang, String inc) {
		setChanged("1");
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");
		Element newInc = null;
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				List languages = element.getChildren("msg");
				for (int j = 0; j < languages.size(); j++) {
					Element language = (Element) languages.get(j);
					if (language.getAttributeValue("lang").equals(lang)) {
						if (null == language.getChild("inc")) {
							List incs = language.getChildren("inc");
							newInc = new Element("inc");
							newInc.setAttribute("msgid", inc);
							incs.add(newInc);
							return;
						}
						return;
					}
				}
			}
		}
	}

	public void delPara(String lang, String msgId) {
		setChanged("1");
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				List languages = element.getChildren("msg");
				for (int j = 0; j < languages.size(); j++) {
					Element language = (Element) languages.get(j);
					if (language.getAttributeValue("lang").equals(lang)) {
						if (null == language.getChild("para")) {
							language.removeContent();
							return;
						}
						List paragraphs = language.getChildren("para");
						for (int l = 0; l < paragraphs.size(); l++) {
							Element para = (Element) paragraphs.get(l);
							if (para.getText().equals(msgId)) {
								paragraphs.remove(para);
								return;
							}
						}
					}
				}
			}
		}
	}

	public void moveUpPara(String lang, String msgId) {
		setChanged("1");
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				List languages = element.getChildren("msg");
				for (int j = 0; j < languages.size(); j++) {
					Element language = (Element) languages.get(j);
					if (language.getAttributeValue("lang").equals(lang)) {
						List paragraphs = language.getChildren("para");
						for (int l = 0; l < paragraphs.size(); l++) {
							Element para = (Element) paragraphs.get(l);
							if (para.getText().equals(msgId)) {
								Element voriges = (Element) paragraphs
										.get(l - 1);
								paragraphs.set(l, voriges.clone());
								paragraphs.set(l - 1, para);
								return;
							}
						}
					}
				}
			}
		}
	}

	public void moveDownPara(String lang, String msgId) {
		setChanged("1");
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				List languages = element.getChildren("msg");
				for (int j = 0; j < languages.size(); j++) {
					Element language = (Element) languages.get(j);
					if (language.getAttributeValue("lang").equals(lang)) {
						List paragraphs = language.getChildren("para");
						for (int l = 0; l < paragraphs.size(); l++) {
							Element para = (Element) paragraphs.get(l);
							if (para.getText().equals(msgId)) {
								Element voriges = (Element) paragraphs
										.get(l + 1);
								paragraphs.set(l, voriges.clone());
								paragraphs.set(l + 1, para);
								return;
							}
						}
					}
				}
			}
		}
	}

	public String[] getLangList() {
		List<String> langListe = new ArrayList<String>();
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			List langNdList = element.getChildren("msg");
			for (int j = 0; j < langNdList.size(); j++) {
				Element language = (Element) langNdList.get(j);
				if (!langListe.contains(language.getAttributeValue("lang")))
					langListe.add(language.getAttributeValue("lang"));
			}
		}
		Collections.sort(langListe, Collator.getInstance());
		String[] array = new String[langListe.size()];
		return langListe.toArray(array);
	}

	public ArrayList<SelectItem> getEmptyLangs() {

		String[] allLangs = getLangList();
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");

		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				List langNdList = element.getChildren("msg");
				String[] availableLangs = new String[langNdList.size()];
				for (int j = 0; j < langNdList.size(); j++) {
					Element language = (Element) langNdList.get(j);
					availableLangs[j] = language.getAttributeValue("lang");
				}

				ArrayList<SelectItem> emptyLangs = new ArrayList();
				for (int j = 0, k = 0; j < allLangs.length; j++) {
					if (!Arrays.asList(availableLangs).contains(allLangs[j])) {
						emptyLangs
								.add(new SelectItem(allLangs[j], allLangs[j]));
						k++;
					}
				}
				return emptyLangs;
			}
		}
		return null;
	}

	public synchronized void saveXML() throws FileNotFoundException,
			IOException {
		// ---- Write XML file ----
		XMLOutputter out = new XMLOutputter();
		out.getFormat().setEncoding("ISO-8859-1");
		out.getFormat().setLineSeparator("\n");
		out.setFormat(Format.getPrettyFormat());
		out.output(xmlDoc.getDoc(), new FileOutputStream(xmlDoc.getFile()));
		setChanged("0");
	}

	private HttpServletRequest getRequest() {
		return (HttpServletRequest) FacesContext.getCurrentInstance()
				.getExternalContext().getRequest();
	}

	public XMLDoc getXmlDoc() {
		return xmlDoc;
	}

	public void setXmlDoc(XMLDoc xmlDoc) {
		this.xmlDoc = xmlDoc;
	}

	public void nextLangElement() {
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");

		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				element = (Element) ndList.get(i + 1);
				getRequest().getSession().setAttribute("translationMsgId",
						element.getAttributeValue("msgid"));
				return;
			}
		}

	}

	public void prevLangElement() {
		String translationMsgId = (String) getRequest().getSession()
				.getAttribute("translationMsgId");

		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(translationMsgId)) {
				element = (Element) ndList.get(i - 1);
				getRequest().getSession().setAttribute("translationMsgId",
						element.getAttributeValue("msgid"));
				return;
			}
		}

	}

	public Boolean existsMsgID(String msgId) {
		Document doc = xmlDoc.getDoc();
		Element root = doc.getRootElement();
		List ndList = root.getChildren("translation");
		for (int i = 0; i < ndList.size(); i++) {
			Element element = (Element) ndList.get(i);
			if (element.getAttributeValue("msgid").equals(msgId)) {
				return true;
			}
		}
		return false;
	}

	public String getChanged() {
		return changed;
	}

	public void setChanged(String changed) {
		getRequest().getSession().setAttribute("changed", changed);
		this.changed = changed;
	}
}
